#include"../common/etcd.hpp"
#include"../common/channel.hpp"
#include "main.pb.h"
#include <gflags/gflags.h>
#include <thread>
#include <brpc/server.h>
#include <butil/logging.h>

DEFINE_bool(run_mode, false, "程序的运行模式, fasle-调试; true-发布;");
DEFINE_string(log_file, "", "发布模式下, 用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下, 用于指定日志输出等级");  //trace default 0

DEFINE_string(etcd_host, "http://127.0.0.1:2379", "这是服务中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(instance_name, "/echo/instance", "当前实例名称");
DEFINE_string(access_host, "127.0.0.1:7070", "当前实例的外部访问地址");
DEFINE_int32(listen_port, 7070, "Rpc服务器监听端口");

//模拟一个小服务
class EchoServiceImpl : public example::EchoService
{
public:
  virtual void Echo(google::protobuf::RpcController* controller,
                       const ::example::EchoRequest* request,
                       ::example::EchoResponse* response,
                       ::google::protobuf::Closure* done)
    {
        /*
            // cntl_base：包含除了 request 和 response 之外的参数集合
            // request: 请求，只读的，来自 client 端的数据包
            // response: 回复。需要用户填充，如果存在 required 字段没有被设置，
            该次调用会失败。
            // done: done 由框架创建，递给服务回调，包含了调用服务回调后的后续
            动作，包括检查 response 正确性，序列化，打包，发送等逻辑。不管成功失败，
            done->Run()必须在请求处理完成后被用户调用一次。
        */
        // 类型于守卫锁，以 ARII 方式自动释放 done 对象 防止忘了调用done的run方法
        brpc::ClosureGuard rpc_guard(done);
        std::cout << "收到消息:" << request->message() << std::endl;    
        
        std::string str = request->message() + "这是一个响应";
        response->set_message(str);
    }
private:
};



int main(int argc, char* argv[])
{
    google::ParseCommandLineFlags(&argc, &argv, true);
    
    init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    //服务端改造思想
    /*  1.构造Echo服务
        2.搭建Rpc服务器
        3.运行Rpc服务*/
        
     //关闭brpc默认日志输出
    logging::LoggingSettings settings;
    settings.logging_dest = logging::LoggingDestination::LOG_TO_NONE;
    logging::InitLogging(settings);

    //2.构造服务对象
    brpc::Server server;
    //3.向服务器对象中， 新增EchoService服务
    EchoServiceImpl echo_service_impl;
        //SERVER_DOESNT_OWN_SERVICE 添加服务失败时 服务器也不会删除对象
    
    int ret = server.AddService(&echo_service_impl, brpc::ServiceOwnership::SERVER_DOESNT_OWN_SERVICE);
    if(ret == -1)
    {
        std::cout << "添加rpc服务 addservice 失败" << std::endl;
        return -1;
    }
    brpc::ServerOptions options;
    options.idle_timeout_sec = -1;  //连接空闲超时时间-超时后连接被关闭
    options.num_threads = 1;        //io线程数量
    //4.启动服务器
    ret = server.Start(FLAGS_listen_port, &options);
    if(ret == 1)
    {
        std::cout << "server 启动失败" << std::endl;
        return -1;
    }

    //4.注册服务
    Registry::ptr rclient = std::make_shared<Registry>(FLAGS_etcd_host);
    //注册的时候 /service/echo/instance 发现的时候/service/echo
    rclient->registry(FLAGS_base_service + FLAGS_instance_name, FLAGS_access_host);


    // 阻塞运行结束
    server.RunUntilAskedToQuit();


    return 0;
}